<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- <link rel="stylesheet" href="./css/继承.css"> -->
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body {
            padding: 20px;
        }

        .box {
            display: flex;
            flex-wrap: wrap;
        }

        .box .item {
            border: 1px solid red;
            width: 190px;
            height: 266px;
            box-sizing: border-box;
            padding: 10px;
            padding-top: 30px;
            display: flex;
            flex-direction: column;
            align-items: center;
            margin: 0 5px 5px 0;
        }

        .box .item>div {
            margin-bottom: 10px;
        }

        .box .item .img {
            width: 120px;
            height: 120px;
        }

        .box .item .img img {
            width: 100%;
            display: block;
        }

        .box .item .text {
            width: 170px;
            height: 40px;
            display: -webkit-box;
            -webkit-box-orient: vertical;
            -webkit-line-clamp: 2;
            overflow: hidden;
        }

        .box .item .footer {
            height: 30px;
            width: 100%;
            display: flex;
            justify-content: space-between;
        }

        .box .item .footer .icon {
            cursor: pointer;
        }
    </style>
</head>

<body>
    <div class="box">

    </div>
    <script>
        //练习
        var box = document.querySelector(".box");
        function Item(item) {
            this.parent = item.parent;
            this.img = item.img;
            this.text = item.text;
            this.price = item.price;
            this.icon = item.icon;
            this.item = null;
        }
        Item.prototype.init = function () {
            this.item = document.createElement("div");
            this.item.classList.add("item");
            this.item.innerHTML = `
                <div class="img">
                    
                </div>
                <div class="text">
                    ${this.text}
                </div>
                <div class="footer">
                    <span>${this.price}</span>
                    <div class="icon"></div>
                </div>`;
            this.item.querySelector(".img").innerHTML = this.img;
            this.item.querySelector(".footer").querySelector(".icon").innerHTML = this.icon;
            this.parent.appendChild(this.item);

        }
        function CartItem(item) {
            Item.call(this, item);
            //Item.call(this, item);
            //为什么这句能实现继承功能
            //在执行这句代码时，会执行Item这个函数，因为是把this绑定过去执行的，Item代码里设置的所有值都是给this新增值，也就是这个对象里
            //在没有call绑定执行时，直接使用Item()，它的this指向window，也就是会全局添加属性，比如下面传进去一个对象cat[0],Item(cat[0])执行代码，因为里面的this指向window，所以里面的所有属性都是为全局设置变量，这时试着在最外层打印一个price，我们没有在全局定义过这个变量，但现在它打印出了一个值；
            //Item(cat[0]);
            // console.log(price);//输出￥300
            //那么我们可以推算new指令创建一个实例对象的的运行过程
            //先创建一个空对象，在这个空对象里面，它的this指向它本身，当我们开始往下执行时，遇到了下面这句
            //Item.call(this, item);
            //Item的this绑定了这个空对象，Item函数里面所有this.XXX的操作都是给这个空对象赋值，执行完这句代码之后，这个对象拥有一些属性值，这些属性值是我们传进去的，因为对象是引用数据类型，Item并不需要返回这个this，在CartItem里这个this一直是指向这个对象，而使用new CartItem()执行完后隐式返回一个this，也就是这个对象，我们最终的关注点仍然是这个对象，我们得到了它，CarItem函数没有为它设置parent，price等等属性值，但CarItem利用Item.call(this, item)，把设置值的工作交给了Item,Item函数做完事后，CartItem再继续操作这个对象，然后隐式返回this，我们在外面可以接收这个this，得到这个对象，在这个过程，CartItem本身是一个制造这个对象的过程函数，也许这也是它叫做构造函数的原因
            //原型链的理解
            //举个例子，Object作为初始构造函数，它是没有原型的，当我们使用Object构造函数创建一个实例对象时，这个实例对象的原型就指向了Object，这样似乎并不好理解，那我们可以尝试换一种思路重新想象一下
            //有一个生灵，里面记录一些方法，它还可以也有一些属性，在这基础上，它可以增加方法，增加属性，这个对象有一个constructor,它的值是一个函数，记录它的本身，它可以用它来做一些事，它还设定有一个__proto__，用来记载它的祖先
            //而Object作为天地间这个系列的第一个生灵，它没有祖先，没有过去，所以它的原型指向(__proto__)为null，在一个世界里，一个人太过孤单，世界主以它本身为模版(constructor)创建了一个新的生灵，新的生灵拥有Object的一切，并且用__proto__记录它的前辈Object，这个新的生灵的的__proto__不再是空，它指向了它的模版Object，后面，世界主又用相同的方式，以这个新生灵为模版，创造了新的生灵，后面还可以不断地继续重复这个过程，每一个新生灵的__proto__都指向它的模版，所有后辈循着这个__proto__，追溯找到最初始的祖先，Object，
            //生灵们在使用方法时，自己没有这个方法，它就会循着这个__proto__向它的父辈询问，父辈不会的话就会问爷爷辈，一直下去，最后问到Object，Object也不会的话，它只能返回一个undefinded，表示这个东西世界主还没教过给它，需要给它定义一下，这一层一层的向上询问，只要找到了就返回，不再向上找了，哪怕更遥远的祖先也有这个方法，但是，大人，时代变了，所有的__proto__链接在一起，形成以一个链式结构，因为proto和prototype(译作原型)长得像，人们把它叫做原型链
            //世界主（我们）可以根据这些生灵，创建一些对象，这些生灵在这个世界，更像是一个个类别，一个个统称，它们独一无二，又可以通过__proto__进行联系，世界里的对象依靠这些类构建，依靠一个类下构建的所有对象，它们的相似点就是这个类
            //有些时候，我们要修改祖先辈的方法，就会使用(对象.__proto__.XXX)来修改，修改后，所有继承这个祖先辈的生灵，调用这个方法时，都会发生变化，除非在那个生灵调用方法时，一直向上询问，在找到这个祖先辈前遇上了有重新定义过这个方法的祖先，根据大人，时代变了的特性，它不会受到影响
            //如果自身添加方法，就直接(对象.XXX)就好，这时只有当前对象有这个方法
            //修改祖先辈的方法，比如下面，所有数组的forEach函数都会变成打印111
            // [].__proto__.forEach = function(){
            //     console.log("111");
            // };
            //修改或者添加自身的方法，不会影响其它人，只有这个[]的forEach变成了打印111
            // [].forEach = function(){
            //     console.log("111");
            // };
            //生灵.prototype.XXX，生灵在调这个增加方法时，貌似会在它和父辈中间创建一个新生灵，里面有定义的方法，还有一个__proto__，指向这个生灵原本的父辈，这时这个生灵的__proto__指向新创建的生灵，然后新创建的生灵的__proto__指向这个生灵原本的__proto__
            //生灵.__proto__.XXX => 生灵的父辈
            //生灵.__proto__.XXX => 新创建的生灵 ，然后， 新创建的生灵.__proto__.XXX =>生灵的父辈
            //多了一个中间层，不妨碍调用，但这个中间层可以截断继续向祖先询问，也就是，大人，时代变了
            this.init();
            this.addCart();
        }
        CartItem.prototype = Object.create(Item.prototype);
        CartItem.prototype.addCart = function () {
            this.item.querySelector(".footer .icon").onclick = function () {
                console.log("我是有购物车方法的");
            }
        }
        function CollectionItem(item) {
            Item.call(this, item);
            this.init();
            this.addCollection();
        }
        CollectionItem.prototype = Object.create(Item.prototype);
        CollectionItem.prototype.addCollection = function () {
            this.item.querySelector(".footer .icon").onclick = function () {
                console.log("我是有收藏方法的");
            }
        }
        var arr = ["购物车", "收藏"];
        var i = 0;
        var cat = [];
        while (++i <= 5) {
            cat.push({
                parent: document.querySelector(".box"),
                img: `<img src="https://img20.360buyimg.com/jdcms/s300x300_jfs/t1/172753/31/24208/126792/613d5801E612ff95c/166b68ab86eb2a4a.jpg.avif" alt="">`,
                text: "蕉色长柄加厚汤勺家用厨具盛粥勺创意厨房用品塑料餐具大号稀饭勺子usr 2只颜色随机",
                price: "¥300",
                icon: `${arr[(Math.random() * (arr.length - 1)) < 0.5 ? 0 : 1]}`
            });
        }
        [].forEach.call(cat, function (item) {
            if (item.icon == "购物车") {
                new CartItem(item);
                return;
            }
            new CollectionItem(item);
        });
        console.log(new CartItem(cat[0]));
    </script>
</body>

</html>